package com.mmp.main.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.Where;

import com.mmp.common.util.SearchRequired;
import com.mmp.main.util.Enums;

/**
 * The persistent class for the job_order database table.
 *
 */
@Entity
@Table(name = "job_order")
@NamedQuery(name = "JobOrder.findAll", query = "SELECT j FROM JobOrder j")
public class JobOrder implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Basic(optional = false)
	private Integer id;

	@ManyToOne(cascade = CascadeType.MERGE)
	@JoinColumn(name = "device_id")
	@SearchRequired(isObject = true, fields = { "serialNo", "code" })
	private HospitalDevice hospitalDevice;

	@Column(name = "job_order_no")
	@SearchRequired
	private String jobOrderNo;

	@ManyToOne
	@JoinColumn(name = "type_id")
	private LookupJobOrderType jobOrderType;

	@ManyToOne
	@JoinColumn(name = "priority_id")
	private LookupJobOrderPriority jobOrderPriority;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "job_order_date")
	private Date jobOrderDate;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "damage_date")
	private Date damageDate;

	@Column(name = "damage_description")
	private String damageDescription;

	@ManyToOne
	@JoinColumn(name = "opened_by")
	private User openedBy;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "opened_in")
	private Date openedIn;

	@Column(name = "request_form_url")
	private String requestFormUrl;

	@ManyToOne
	@JoinColumn(name = "responsible_engineer")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee responsibleEngineer;

	@ManyToOne
	@JoinColumn(name = "related_hospital_department_head")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee relatedHospitalDepartmentHead;

	@ManyToOne
	@JoinColumn(name = "site_manager")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee siteManager;

	@ManyToOne
	@JoinColumn(name = "mmp_department_head")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee mmpDepartmentHead;

	@ManyToOne
	@JoinColumn(name = "hospital_assistant_director")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee hospitalAssistantDirector;

	@ManyToOne
	@JoinColumn(name = "hospital_director")
	@NotFound(action = NotFoundAction.IGNORE)
	private Employee hospitalDirector;

	@SearchRequired
	private Boolean cancelled;

	@ManyToOne
	@JoinColumn(name = "cancelled_by")
	private User cancelledBy;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "cancelled_in")
	private Date cancelledIn;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "actual_cancel_date")
	private Date actualCancelDate;

	@Column(name = "cancel_reason")
	private String cancelReason;

	@SearchRequired
	private Boolean closed;

	@ManyToOne
	@JoinColumn(name = "closed_by")
	private User closedBy;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "closed_in")
	private Date closedIn;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "actual_close_date")
	private Date actualCloseDate;

	@Column(name = "fix_including_spare_parts")
	private Boolean fixIncludingSpareParts;

	@Column(name = "sp_source")
	private Integer spSource;

	@Column(name = "sp_po_scan_url")
	private String spPoScanUrl;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "inventory_transaction_date")
	private Date inventoryTransactionDate;

	@Column(name = "agent_report_url")
	private String agentReportUrl;

	@Column(name = "quotation_recieved")
	private Boolean quotationRecieved;

	@Column(name = "quotation_scan_url")
	private String quotationScanUrl;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "quotation_date")
	private Date quotationDate;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "quotation_expire_date")
	private Date quotationExpireDate;

	@Column(name = "quotation_accepted")
	private Boolean quotationAccepted;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "quotation_acceptance_date")
	private Date quotationAcceptanceDate;

	@Column(name = "quotation_acceptance_no")
	private String quotationAcceptanceNo;

	@Column(name = "first_action")
	private String firstAction;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "first_action_date")
	private Date firstActionDate;

	@Column(name = "agent_must_attend")
	private Boolean agentMustAttend;

	@Column(name = "second_action")
	private String secondAction;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "second_action_date")
	private Date secondActionDate;

	@Column(name = "final_action")
	private String finalAction;

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "final_action_date")
	private Date finalActionDate;

	@Column(name = "final_agent_report_url")
	private String finalAgentReportUrl;

	@Column(name = "final_report_url")
	private String finalReportUrl;

	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(cascade = CascadeType.ALL, mappedBy = "jobOrder", orphanRemoval = true)
	@Where(clause = "in_quotation is null")
	private List<JobOrderSparePart> jobOrderSpareParts;

	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(cascade = CascadeType.ALL, mappedBy = "jobOrder", orphanRemoval = true)
	@Where(clause = "in_quotation = 1")
	private List<JobOrderSparePart> sparePartsInsideQuotation;

	@LazyCollection(LazyCollectionOption.FALSE)
	@OneToMany(cascade = CascadeType.ALL, mappedBy = "jobOrder", orphanRemoval = true)
	@Where(clause = "in_quotation = 0")
	private List<JobOrderSparePart> sparePartsOutsideQuotation;

	@Column(name = "last_completed_phase_id")
	private Integer lastCompletedPhaseId;

	public JobOrder() {
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public HospitalDevice getHospitalDevice() {
		return hospitalDevice;
	}

	public void setHospitalDevice(HospitalDevice hospitalDevice) {
		this.hospitalDevice = hospitalDevice;
	}

	public String getJobOrderNo() {
		return jobOrderNo;
	}

	public void setJobOrderNo(String jobOrderNo) {
		this.jobOrderNo = jobOrderNo;
	}

	public LookupJobOrderType getJobOrderType() {
		return jobOrderType;
	}

	public void setJobOrderType(LookupJobOrderType jobOrderType) {
		this.jobOrderType = jobOrderType;
	}

	public LookupJobOrderPriority getJobOrderPriority() {
		return jobOrderPriority;
	}

	public void setJobOrderPriority(LookupJobOrderPriority jobOrderPriority) {
		this.jobOrderPriority = jobOrderPriority;
	}

	public Date getJobOrderDate() {
		return jobOrderDate;
	}

	public void setJobOrderDate(Date jobOrderDate) {
		this.jobOrderDate = jobOrderDate;
	}

	public Date getDamageDate() {
		return damageDate;
	}

	public void setDamageDate(Date damageDate) {
		this.damageDate = damageDate;
	}

	public String getDamageDescription() {
		return damageDescription;
	}

	public void setDamageDescription(String damageDescription) {
		this.damageDescription = damageDescription;
	}

	public User getOpenedBy() {
		return openedBy;
	}

	public void setOpenedBy(User openedBy) {
		this.openedBy = openedBy;
	}

	public Date getOpenedIn() {
		return openedIn;
	}

	public void setOpenedIn(Date openedIn) {
		this.openedIn = openedIn;
	}

	public String getRequestFormUrl() {
		return requestFormUrl;
	}

	public void setRequestFormUrl(String requestFormUrl) {
		this.requestFormUrl = requestFormUrl;
	}

	public Employee getResponsibleEngineer() {
		return responsibleEngineer;
	}

	public void setResponsibleEngineer(Employee responsibleEngineer) {
		this.responsibleEngineer = responsibleEngineer;
	}

	public Employee getRelatedHospitalDepartmentHead() {
		return relatedHospitalDepartmentHead;
	}

	public void setRelatedHospitalDepartmentHead(Employee relatedHospitalDepartmentHead) {
		this.relatedHospitalDepartmentHead = relatedHospitalDepartmentHead;
	}

	public Employee getSiteManager() {
		return siteManager;
	}

	public void setSiteManager(Employee siteManager) {
		this.siteManager = siteManager;
	}

	public Employee getMmpDepartmentHead() {
		return mmpDepartmentHead;
	}

	public void setMmpDepartmentHead(Employee mmpDepartmentHead) {
		this.mmpDepartmentHead = mmpDepartmentHead;
	}

	public Employee getHospitalAssistantDirector() {
		return hospitalAssistantDirector;
	}

	public void setHospitalAssistantDirector(Employee hospitalAssistantDirector) {
		this.hospitalAssistantDirector = hospitalAssistantDirector;
	}

	public Employee getHospitalDirector() {
		return hospitalDirector;
	}

	public void setHospitalDirector(Employee hospitalDirector) {
		this.hospitalDirector = hospitalDirector;
	}

	public Boolean getCancelled() {
		return cancelled;
	}

	public void setCancelled(Boolean cancelled) {
		this.cancelled = cancelled;
	}

	public User getCancelledBy() {
		return cancelledBy;
	}

	public void setCancelledBy(User cancelledBy) {
		this.cancelledBy = cancelledBy;
	}

	public Date getCancelledIn() {
		return cancelledIn;
	}

	public void setCancelledIn(Date cancelledIn) {
		this.cancelledIn = cancelledIn;
	}

	public Date getActualCancelDate() {
		return actualCancelDate;
	}

	public void setActualCancelDate(Date actualCancelDate) {
		this.actualCancelDate = actualCancelDate;
	}

	public String getCancelReason() {
		return cancelReason;
	}

	public void setCancelReason(String cancelReason) {
		this.cancelReason = cancelReason;
	}

	public Boolean getClosed() {
		return closed;
	}

	public void setClosed(Boolean closed) {
		this.closed = closed;
	}

	public User getClosedBy() {
		return closedBy;
	}

	public void setClosedBy(User closedBy) {
		this.closedBy = closedBy;
	}

	public Date getClosedIn() {
		return closedIn;
	}

	public void setClosedIn(Date closedIn) {
		this.closedIn = closedIn;
	}

	public Date getActualCloseDate() {
		return actualCloseDate;
	}

	public void setActualCloseDate(Date actualCloseDate) {
		this.actualCloseDate = actualCloseDate;
	}

	public Boolean getFixIncludingSpareParts() {
		return fixIncludingSpareParts;
	}

	public void setFixIncludingSpareParts(Boolean fixIncludingSpareParts) {
		this.fixIncludingSpareParts = fixIncludingSpareParts;
	}

	public Integer getSpSource() {
		return spSource;
	}

	public void setSpSource(Integer spSource) {
		this.spSource = spSource;
	}

	public String getSpPoScanUrl() {
		return spPoScanUrl;
	}

	public void setSpPoScanUrl(String spPoScanUrl) {
		this.spPoScanUrl = spPoScanUrl;
	}

	public Date getInventoryTransactionDate() {
		return inventoryTransactionDate;
	}

	public void setInventoryTransactionDate(Date inventoryTransactionDate) {
		this.inventoryTransactionDate = inventoryTransactionDate;
	}

	public String getAgentReportUrl() {
		return agentReportUrl;
	}

	public void setAgentReportUrl(String agentReportUrl) {
		this.agentReportUrl = agentReportUrl;
	}

	public Boolean getQuotationRecieved() {
		return quotationRecieved;
	}

	public void setQuotationRecieved(Boolean quotationRecieved) {
		this.quotationRecieved = quotationRecieved;
	}

	public String getQuotationScanUrl() {
		return quotationScanUrl;
	}

	public void setQuotationScanUrl(String quotationScanUrl) {
		this.quotationScanUrl = quotationScanUrl;
	}

	public Date getQuotationDate() {
		return quotationDate;
	}

	public void setQuotationDate(Date quotationDate) {
		this.quotationDate = quotationDate;
	}

	public Date getQuotationExpireDate() {
		return quotationExpireDate;
	}

	public void setQuotationExpireDate(Date quotationExpireDate) {
		this.quotationExpireDate = quotationExpireDate;
	}

	public Boolean getQuotationAccepted() {
		return quotationAccepted;
	}

	public void setQuotationAccepted(Boolean quotationAccepted) {
		this.quotationAccepted = quotationAccepted;
	}

	public Date getQuotationAcceptanceDate() {
		return quotationAcceptanceDate;
	}

	public void setQuotationAcceptanceDate(Date quotationAcceptanceDate) {
		this.quotationAcceptanceDate = quotationAcceptanceDate;
	}

	public String getQuotationAcceptanceNo() {
		return quotationAcceptanceNo;
	}

	public void setQuotationAcceptanceNo(String quotationAcceptanceNo) {
		this.quotationAcceptanceNo = quotationAcceptanceNo;
	}

	public String getFirstAction() {
		return firstAction;
	}

	public void setFirstAction(String firstAction) {
		this.firstAction = firstAction;
	}

	public Date getFirstActionDate() {
		return firstActionDate;
	}

	public void setFirstActionDate(Date firstActionDate) {
		this.firstActionDate = firstActionDate;
	}

	public Boolean getAgentMustAttend() {
		return agentMustAttend;
	}

	public void setAgentMustAttend(Boolean agentMustAttend) {
		this.agentMustAttend = agentMustAttend;
	}

	public String getSecondAction() {
		return secondAction;
	}

	public void setSecondAction(String secondAction) {
		this.secondAction = secondAction;
	}

	public Date getSecondActionDate() {
		return secondActionDate;
	}

	public void setSecondActionDate(Date secondActionDate) {
		this.secondActionDate = secondActionDate;
	}

	public String getFinalAction() {
		return finalAction;
	}

	public void setFinalAction(String finalAction) {
		this.finalAction = finalAction;
	}

	public Date getFinalActionDate() {
		return finalActionDate;
	}

	public void setFinalActionDate(Date finalActionDate) {
		this.finalActionDate = finalActionDate;
	}

	public String getFinalAgentReportUrl() {
		return finalAgentReportUrl;
	}

	public void setFinalAgentReportUrl(String finalAgentReportUrl) {
		this.finalAgentReportUrl = finalAgentReportUrl;
	}

	public String getFinalReportUrl() {
		return finalReportUrl;
	}

	public void setFinalReportUrl(String finalReportUrl) {
		this.finalReportUrl = finalReportUrl;
	}

	public List<JobOrderSparePart> getJobOrderSpareParts() {
		return this.jobOrderSpareParts;
	}

	public void setJobOrderSpareParts(List<JobOrderSparePart> jobOrderSpareParts) {
		this.jobOrderSpareParts = jobOrderSpareParts;
	}

	public JobOrderSparePart addJobOrderSparePart(JobOrderSparePart jobOrderSparePart) {
		getJobOrderSpareParts().add(jobOrderSparePart);
		jobOrderSparePart.setJobOrder(this);

		return jobOrderSparePart;
	}

	public JobOrderSparePart removeJobOrderSparePart(JobOrderSparePart jobOrderSparePart) {
		getJobOrderSpareParts().remove(jobOrderSparePart);
		jobOrderSparePart.setJobOrder(null);

		return jobOrderSparePart;
	}

	public List<JobOrderSparePart> getSparePartsInsideQuotation() {
		return sparePartsInsideQuotation;
	}

	public void setSparePartsInsideQuotation(List<JobOrderSparePart> sparePartsInsideQuotation) {
		this.sparePartsInsideQuotation = sparePartsInsideQuotation;
	}

	public JobOrderSparePart addSparePartsInsideQuotation(JobOrderSparePart sparePartsInsideQuotation) {
		getSparePartsInsideQuotation().add(sparePartsInsideQuotation);
		sparePartsInsideQuotation.setJobOrder(this);

		return sparePartsInsideQuotation;
	}

	public JobOrderSparePart removeSparePartsInsideQuotation(JobOrderSparePart sparePartsInsideQuotation) {
		getSparePartsInsideQuotation().remove(sparePartsInsideQuotation);
		sparePartsInsideQuotation.setJobOrder(null);

		return sparePartsInsideQuotation;
	}

	public List<JobOrderSparePart> getSparePartsOutsideQuotation() {
		return sparePartsOutsideQuotation;
	}

	public void setSparePartsOutsideQuotation(List<JobOrderSparePart> sparePartsOutsideQuotation) {
		this.sparePartsOutsideQuotation = sparePartsOutsideQuotation;
	}

	public JobOrderSparePart addSparePartsOutsideQuotation(JobOrderSparePart sparePartsOutsideQuotation) {
		getSparePartsOutsideQuotation().add(sparePartsOutsideQuotation);
		sparePartsOutsideQuotation.setJobOrder(this);

		return sparePartsOutsideQuotation;
	}

	public JobOrderSparePart removeSparePartsOutsideQuotation(JobOrderSparePart sparePartsOutsideQuotation) {
		getSparePartsOutsideQuotation().remove(sparePartsOutsideQuotation);
		sparePartsOutsideQuotation.setJobOrder(null);

		return sparePartsOutsideQuotation;
	}

	public Integer getLastCompletedPhaseId() {
		return lastCompletedPhaseId;
	}

	public void setLastCompletedPhaseId(Integer lastCompletedPhaseId) {
		this.lastCompletedPhaseId = lastCompletedPhaseId;
	}

	public List<JobOrderSparePart> getSpareParts() {

		if (lastCompletedPhaseId == Enums.JOBORDER_FOLLOWUP_PHASES.NOT_HANDLED_YET.getId()
				|| lastCompletedPhaseId == Enums.JOBORDER_FOLLOWUP_PHASES.FIRST_ACTION_TAKEN.getId())
			return getDummySparePartsList();

		if (fixIncludingSpareParts != null && !fixIncludingSpareParts)
			return null;

		List<JobOrderSparePart> list = null;

		if (spSource != Enums.JOBORDER_SP_SOURCES.AGENT.getId())
			list = jobOrderSpareParts;
		else if (sparePartsInsideQuotation != null && !sparePartsInsideQuotation.isEmpty()) {
			if (sparePartsOutsideQuotation != null && !sparePartsOutsideQuotation.isEmpty())
				sparePartsInsideQuotation.addAll(sparePartsOutsideQuotation);
			list = sparePartsInsideQuotation;
		}

		return (list == null || list.isEmpty()) ? getDummySparePartsList() : list;
	}

	private List<JobOrderSparePart> getDummySparePartsList() {
		List<JobOrderSparePart> list = new ArrayList<JobOrderSparePart>(8);
		for (int i = 0; i < 7; i++)
			list.add(new JobOrderSparePart());
		return list;
	}

	public String getCurrentPhaseName() {
		String name = null;
		if (lastCompletedPhaseId == Enums.JOBORDER_FOLLOWUP_PHASES.NOT_HANDLED_YET.getId())
			name = "تم استلام بلاغ عن العطل";
		else {
			if (fixIncludingSpareParts == null)
				if (agentMustAttend == false)
					name = "جاري فحص وتحديد العطل";
				else
					name = "في انتظار حضور الوكيل";
			else if (fixIncludingSpareParts == false)
				name = "جاري الإصلاح";
			else if (fixIncludingSpareParts == true)
				if (spSource != Enums.JOBORDER_SP_SOURCES.AGENT.getId())
					name = "جاري الإصلاح";
				else if (quotationRecieved == null)
					name = "في انتظار عرض السعر";
				else if (quotationAccepted == null)
					name = "جاري التعميد";
				else
					name = "في انتظار قطع الغيار";

		}

		return name;
	}

	public float getSparePartsTotalCost() {
		float sum = 0;
		if (jobOrderSpareParts != null)
			for (JobOrderSparePart p : jobOrderSpareParts)
				sum += p.getTotalPrice();
		return sum;
	}

}
